use core::{Package, PackageId, PackageSet, Resolve, Target, Profile};
use core::{TargetKind, Profiles, Dependency, Workspace};
use core::dependency::Kind as DepKind;
-use util::{self, CargoResult, ChainError, internal, Config, profile, Cfg, human};
+use util::{self, CargoResult, ChainError, internal, Config, profile, Cfg, CfgExpr, human};
use super::TargetConfig;
use super::custom_build::{BuildState, BuildScripts};
-> CargoResult<()> {
let rustflags = env_args(self.config,
&self.build_config,
+ &self.info(&kind),
kind,
"RUSTFLAGS")?;
let mut process = self.config.rustc()?.process();
}
pub fn rustflags_args(&self, unit: &Unit) -> CargoResult<Vec<String>> {
- env_args(self.config, &self.build_config, unit.kind, "RUSTFLAGS")
+ env_args(self.config, &self.build_config, self.info(&unit.kind), unit.kind, "RUSTFLAGS")
}
pub fn rustdocflags_args(&self, unit: &Unit) -> CargoResult<Vec<String>> {
- env_args(self.config, &self.build_config, unit.kind, "RUSTDOCFLAGS")
+ env_args(self.config, &self.build_config, self.info(&unit.kind), unit.kind, "RUSTDOCFLAGS")
}
pub fn show_warnings(&self, pkg: &PackageId) -> bool {
pkg.source_id().is_path() || self.config.extra_verbose()
}
+
+ fn info(&self, kind: &Kind) -> &TargetInfo {
+ match *kind {
+ Kind::Host => &self.host_info,
+ Kind::Target => &self.target_info,
+ }
+ }
}
// Acquire extra flags to pass to the compiler from the
// RUSTFLAGS environment variable and similar config values
fn env_args(config: &Config,
build_config: &BuildConfig,
+ target_info: &TargetInfo,
kind: Kind,
name: &str) -> CargoResult<Vec<String>> {
// We *want* to apply RUSTFLAGS only to builds for the
return Ok(args.collect());
}
+ let mut rustflags = Vec::new();
+
let name = name.chars().flat_map(|c| c.to_lowercase()).collect::<String>();
- // Then the target.*.rustflags value
+ // Then the target.*.rustflags value...
let target = build_config.requested_target.as_ref().unwrap_or(&build_config.host_triple);
let key = format!("target.{}.{}", target, name);
if let Some(args) = config.get_list_or_split_string(&key)? {
let args = args.val.into_iter();
- return Ok(args.collect());
+ rustflags.extend(args);
+ }
+ // ...including target.'cfg(...)'.rustflags
+ if let Some(ref target_cfg) = target_info.cfg {
+ if let Some(table) = config.get_table("target")? {
+ let cfgs = table.val.iter().map(|(t, _)| (CfgExpr::from_str(t), t))
+ .filter_map(|(c, n)| c.map(|c| (c, n)).ok())
+ .filter(|&(ref c, _)| c.matches(target_cfg));
+ for (_, n) in cfgs {
+ let key = format!("target.'{}'.{}", n, name);
+ if let Some(args) = config.get_list_or_split_string(&key)? {
+ let args = args.val.into_iter();
+ rustflags.extend(args);
+ }
+ }
+ }
+ }
+
+ if !rustflags.is_empty() {
+ return Ok(rustflags);
}
// Then the build.rustflags value
# For the following sections, $triple refers to any valid target triple, not the
# literal string "$triple", and it will apply whenever that target triple is
-# being compiled to.
+# being compiled to. 'cfg(...)' refers to the Rust-like `#[cfg]` syntax for
+# conditional compilation.
[target]
# For Cargo builds which do not mention --target, this is the linker
# which is passed to rustc (via `-C linker=`). By default this flag is not
# this value overrides build.rustflags when both are present
rustflags = ["..", ".."]
+[target.'cfg(...)']
+# Similar for the $triple configuration, but using the `cfg` syntax.
+# If several `cfg` and $triple targets are candidates, then the rustflags
+# are concatenated. The `cfg` syntax only applies to rustflags, and not to
+# linker.
+rustflags = ["..", ".."]
+
# Configuration keys related to the registry
[registry]
index = "..." # URL of the registry index (defaults to the central repository)
execs().with_status(101));
}
+#[test]
+fn cfg_rustflags_normal_source() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ "#)
+ .file("src/lib.rs", "")
+ .file("src/bin/a.rs", "fn main() {}")
+ .file("examples/b.rs", "fn main() {}")
+ .file("tests/c.rs", "#[test] fn f() { }")
+ .file("benches/d.rs", r#"
+ #![feature(test)]
+ extern crate test;
+ #[bench] fn run1(_ben: &mut test::Bencher) { }"#)
+ .file(".cargo/config", "
+ [target.'cfg(feature=\"feat\")']
+ rustflags = [\"-Z\", \"bogus\"]
+ ");
+ p.build();
+
+ assert_that(p.cargo("build").arg("--features").arg("\"feat\"")
+ .arg("--lib"),
+ execs().with_status(101));
+ assert_that(p.cargo("build").arg("--features").arg("\"feat\"")
+ .arg("--bin=a"),
+ execs().with_status(101));
+ assert_that(p.cargo("build").arg("--features").arg("\"feat\"")
+ .arg("--example=b"),
+ execs().with_status(101));
+ assert_that(p.cargo("test").arg("--features").arg("\"feat\""),
+ execs().with_status(101));
+ assert_that(p.cargo("bench").arg("--features").arg("\"feat\""),
+ execs().with_status(101));
+}
+
+// target.'cfg(...)'.rustflags takes precedence over build.rustflags
+#[test]
+fn cfg_rustflags_precedence() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ "#)
+ .file("src/lib.rs", "")
+ .file(".cargo/config", "
+ [build]
+ rustflags = [\"--cfg\", \"foo\"]
+
+ [target.'cfg(feature = \"feat\"')]
+ rustflags = [\"-Z\", \"bogus\"]
+ ");
+ p.build();
+
+ assert_that(p.cargo("build").arg("--features").arg("\"feat\"")
+ .arg("--lib"),
+ execs().with_status(101));
+ assert_that(p.cargo("build").arg("--features").arg("\"feat\"")
+ .arg("--bin=a"),
+ execs().with_status(101));
+ assert_that(p.cargo("build").arg("--features").arg("\"feat\"")
+ .arg("--example=b"),
+ execs().with_status(101));
+ assert_that(p.cargo("test").arg("--features").arg("\"feat\""),
+ execs().with_status(101));
+ assert_that(p.cargo("bench").arg("--features").arg("\"feat\""),
+ execs().with_status(101));
+}
+
+
+
#[test]
fn target_rustflags_string_and_array_form1() {
let p1 = project("foo")